from PySide6 import QtCore, QtGui, QtWidgets
import os
import threading
from datetime import datetime

from app.batch_processor import BatchProcessor
from app.config import APP_SETTINGS
from utils.helpers import parse_quarters, is_valid_quarter_format


class ProgressSignals(QtCore.QObject):
	progress_changed = QtCore.Signal(int, str)
	log_appended = QtCore.Signal(str)
	status_changed = QtCore.Signal(str)
	enable_controls = QtCore.Signal(bool)
	result_dir_changed = QtCore.Signal(str)


class QtExtractorWindow(QtWidgets.QMainWindow):
	def __init__(self):
		super().__init__()
		self.setWindowTitle("个人剂量监测报告批量提取工具")
		self.resize(1000, 720)
		self.setMinimumSize(900, 600)

		self.signals = ProgressSignals()
		self.signals.progress_changed.connect(self.on_progress_changed)
		self.signals.log_appended.connect(self.append_log)
		self.signals.status_changed.connect(self.on_status_changed)
		self.signals.enable_controls.connect(self.enable_controls)
		self.signals.result_dir_changed.connect(self.on_result_dir_changed)

		self._build_ui()
		self._wire_events()

	def _build_ui(self):
		central = QtWidgets.QWidget()
		central.setObjectName("central")
		self.setCentralWidget(central)

		# 全局布局
		layout = QtWidgets.QVBoxLayout(central)
		layout.setContentsMargins(16, 16, 16, 16)
		layout.setSpacing(12)

		# 标题卡片
		self.header_card = self._create_card()
		layout.addWidget(self.header_card)
		h_title = QtWidgets.QVBoxLayout(self.header_card)
		title = QtWidgets.QLabel("个人剂量监测报告批量提取工具")
		title.setStyleSheet("font-size:20px;font-weight:700;color:#1F2937;")
		h_title.addWidget(title)
		sub = QtWidgets.QLabel("医疗数据批量处理 · 高效 · 准确 · 专业")
		sub.setStyleSheet("color:#6B7280;margin-top:2px;")
		h_title.addWidget(sub)

		# 输入配置卡片
		self.input_card = self._create_card()
		layout.addWidget(self.input_card)
		in_lay = QtWidgets.QGridLayout(self.input_card)
		in_lay.setHorizontalSpacing(8)
		in_lay.setVerticalSpacing(8)
		in_lay.setColumnStretch(1, 1)

		# 数据目录
		in_lay.addWidget(self._section_label("数据目录"), 0, 0)
		self.data_dir_edit = QtWidgets.QLineEdit()
		self.data_dir_edit.setPlaceholderText("选择包含季度数据的目录，例如 data/")
		in_lay.addWidget(self.data_dir_edit, 0, 1)
		self.browse_btn = QtWidgets.QPushButton("浏览...")
		self.browse_btn.setProperty("variant", "outline")
		self.browse_btn.setMinimumWidth(100)
		in_lay.addWidget(self.browse_btn, 0, 2)

		# 时间范围
		in_lay.addWidget(self._section_label("时间范围"), 1, 0)
		self.time_edit = QtWidgets.QLineEdit()
		self.time_edit.setPlaceholderText("例如: 2025Q1-2025Q2 或 2025Q1")
		self.time_edit.setText("2025Q1-2025Q2")
		in_lay.addWidget(self.time_edit, 1, 1)
		self.hint_label = QtWidgets.QLabel("例如: 2025Q1-2025Q2 或 2025Q1")
		self.hint_label.setStyleSheet("color:#6B7280;")
		in_lay.addWidget(self.hint_label, 1, 2)

		# 校验状态
		self.status_row = QtWidgets.QHBoxLayout()
		in_lay.addLayout(self.status_row, 2, 0, 1, 3)
		self.validate_label_title = QtWidgets.QLabel("检查状态:")
		self.validate_label_title.setStyleSheet("font-weight:600;")
		self.status_row.addWidget(self.validate_label_title)
		self.validate_label = QtWidgets.QLabel("")
		self.status_row.addWidget(self.validate_label)
		self.status_row.addStretch()

		# 控制区卡片
		self.control_card = self._create_card()
		layout.addWidget(self.control_card)
		ctrl = QtWidgets.QHBoxLayout(self.control_card)
		self.start_btn = QtWidgets.QPushButton("开始处理")
		self.start_btn.setEnabled(False)
		self.open_btn = QtWidgets.QPushButton("打开结果目录")
		self.open_btn.setEnabled(False)
		self.clear_btn = QtWidgets.QPushButton("清空日志")
		for b in (self.start_btn, self.open_btn, self.clear_btn):
			b.setMinimumWidth(120)
			b.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
		# 按钮视觉变体
		self.start_btn.setProperty("variant", "primary")
		self.open_btn.setProperty("variant", "outline")
		self.clear_btn.setProperty("variant", "outline")
		ctrl.addStretch()
		ctrl.addWidget(self.start_btn)
		ctrl.addWidget(self.open_btn)
		ctrl.addWidget(self.clear_btn)
		ctrl.addStretch()

		# 进度卡片
		self.progress_card = self._create_card()
		layout.addWidget(self.progress_card)
		p_lay = QtWidgets.QVBoxLayout(self.progress_card)
		p_top = QtWidgets.QHBoxLayout()
		self.progress_title = QtWidgets.QLabel("处理进度")
		self.progress_title.setStyleSheet("font-weight:600;")
		p_top.addWidget(self.progress_title)
		self.status_label = QtWidgets.QLabel("就绪")
		self.status_label.setStyleSheet("color:#059669;")
		p_top.addStretch()
		p_top.addWidget(self.status_label)
		p_lay.addLayout(p_top)
		self.progress_bar = QtWidgets.QProgressBar()
		self.progress_bar.setRange(0, 100)
		self.progress_bar.setValue(0)
		self.progress_bar.setTextVisible(False)
		self.progress_bar.setFixedHeight(10)
		self.progress_bar.setStyleSheet("QProgressBar{background:#E5E7EB;border-radius:5px;} QProgressBar::chunk{background:#2563EB;border-radius:5px;}")
		p_lay.addWidget(self.progress_bar)
		self.progress_percent = QtWidgets.QLabel("")
		self.progress_percent.setStyleSheet("color:#6B7280;")
		p_lay.addWidget(self.progress_percent)

		# 日志卡片
		self.log_card = self._create_card()
		layout.addWidget(self.log_card, 1)
		log_lay = QtWidgets.QVBoxLayout(self.log_card)
		log_lay.addWidget(self._section_label("处理日志"))
		self.log_text = QtWidgets.QPlainTextEdit()
		self.log_text.setReadOnly(True)
		self.log_text.setStyleSheet("font-family:Consolas, monospace; background:#F9FAFB;")
		log_lay.addWidget(self.log_text)

		# 结果卡片
		self.result_card = self._create_card()
		layout.addWidget(self.result_card)
		r_lay = QtWidgets.QGridLayout(self.result_card)
		r_lay.addWidget(self._section_label("结果目录"), 0, 0)
		self.result_edit = QtWidgets.QLineEdit()
		self.result_edit.setReadOnly(True)
		r_lay.addWidget(self.result_edit, 0, 1)

		# 全局样式
		self.setStyleSheet(self._style_sheet())

	def _style_sheet(self) -> str:
		# 统一浅色企业风样式（主色 #2563EB）
		return (
			"QWidget{font-family:'Microsoft YaHei','PingFang SC','Helvetica';font-size:12px;color:#111827;}"
			"QWidget#central{background:#F5F6F8;}"
			"QLineEdit, QPlainTextEdit{border:1px solid #D1D5DB;border-radius:8px;padding:8px;background:white;}"
			"QLineEdit:focus, QPlainTextEdit:focus{border:1px solid #2563EB;}"
			"QPushButton{border-radius:8px;padding:10px 16px;}"
			"QPushButton[variant='primary']{background:#2563EB;color:white;border:1px solid #2563EB;}"
			"QPushButton[variant='primary']:hover{background:#1D4ED8;border-color:#1D4ED8;}"
			"QPushButton[variant='primary']:disabled{background:#9CA3AF;border-color:#9CA3AF;color:white;}"
			"QPushButton[variant='outline']{background:white;color:#1F2937;border:1px solid #D1D5DB;}"
			"QPushButton[variant='outline']:hover{background:#F9FAFB;border-color:#CBD5E1;}"
			"QPushButton[variant='outline']:disabled{color:#9CA3AF;border-color:#E5E7EB;background:white;}"
			"QGroupBox{border:none;}"
		)

	def _create_card(self) -> QtWidgets.QFrame:
		card = QtWidgets.QFrame()
		card.setObjectName("card")
		card.setStyleSheet("QFrame#card{background:white;border:1px solid #E5E7EB;border-radius:12px;}")
		# 添加轻微阴影
		self._apply_shadow(card)
		return card

	def _apply_shadow(self, widget: QtWidgets.QWidget):
		shadow = QtWidgets.QGraphicsDropShadowEffect(widget)
		shadow.setBlurRadius(16)
		shadow.setOffset(0, 2)
		shadow.setColor(QtGui.QColor(0, 0, 0, 28))
		widget.setGraphicsEffect(shadow)

	def _section_label(self, text: str) -> QtWidgets.QLabel:
		lbl = QtWidgets.QLabel(text)
		lbl.setStyleSheet("font-weight:600;color:#374151;")
		return lbl

	def _wire_events(self):
		self.browse_btn.clicked.connect(self.browse_data_dir)
		self.clear_btn.clicked.connect(lambda: self.log_text.setPlainText(""))
		self.start_btn.clicked.connect(self.start_processing)
		self.open_btn.clicked.connect(self.open_result_directory)
		self.data_dir_edit.textChanged.connect(self.validate_inputs)
		self.time_edit.textChanged.connect(self.validate_inputs)
		self.validate_inputs()

	def append_log(self, text: str):
		ts = datetime.now().strftime('%H:%M:%S')
		self.log_text.appendPlainText(f"[{ts}] {text}")

	def on_progress_changed(self, value: int, text: str):
		self.progress_bar.setValue(int(value))
		self.progress_percent.setText(f"{value:.0f}% {text}")

	def on_status_changed(self, text: str):
		self.status_label.setText(text)

	def enable_controls(self, enabled: bool):
		self.start_btn.setEnabled(enabled)
		self.open_btn.setEnabled(enabled)

	def on_result_dir_changed(self, path: str):
		self.result_edit.setText(path)

	def browse_data_dir(self):
		path = QtWidgets.QFileDialog.getExistingDirectory(self, "选择数据目录", self.data_dir_edit.text() or os.getcwd())
		if path:
			self.data_dir_edit.setText(path)

	def validate_inputs(self):
		errors = []
		ok = True
		time_range = self.time_edit.text().strip()
		quarters = []
		if not time_range:
			errors.append("请输入时间范围")
			ok = False
		else:
			if '-' in time_range:
				parts = time_range.split('-')
				if len(parts) != 2 or not all(is_valid_quarter_format(p.strip()) for p in parts):
					ok = False
					errors.append("时间范围格式错误")
				else:
					quarters = parse_quarters(time_range)
			else:
				if not is_valid_quarter_format(time_range):
					ok = False
					errors.append("时间范围格式错误")
				else:
					quarters = parse_quarters(time_range)

		data_dir = self.data_dir_edit.text().strip()
		if data_dir:
			# 有数据目录：需要检查目录和必需子目录、Excel
			if not os.path.isdir(data_dir):
				ok = False
				errors.append("数据目录不存在")
			else:
				# 检查季度子目录
				missing = []
				for q in quarters:
					q_dir = os.path.join(data_dir, q)
					if not os.path.isdir(q_dir):
						missing.append(q)
				if missing:
					ok = False
					errors.append("缺少季度目录: " + ", ".join(missing))
				# 检查Excel查询文件
				excel_path = os.path.join(data_dir, "个人剂量监测各单位编号汇总.xlsx")
				if not os.path.isfile(excel_path):
					ok = False
					errors.append("缺少Excel查询文件: 个人剂量监测各单位编号汇总.xlsx")
		else:
			# 无数据目录：检查历史季度CSV是否存在
			archives_dir = os.path.join(os.getcwd(), APP_SETTINGS['QUARTERLY_ARCHIVES_DIR'])
			missing_h = []
			for q in quarters:
				csv_path = os.path.join(archives_dir, f"{q}季度汇总表.csv")
				if not os.path.isfile(csv_path):
					missing_h.append(q)
			if missing_h:
				ok = False
				errors.append("缺少历史季度数据: " + ", ".join(missing_h))

		self.validate_label.setText("检查通过，可以开始处理" if ok else "; ".join(errors))
		self.validate_label.setStyleSheet("color:#059669;" if ok else "color:#DC2626;")
		self.start_btn.setEnabled(ok)

	def start_processing(self):
		if not self.start_btn.isEnabled():
			return
		self.signals.enable_controls.emit(False)
		self.signals.status_changed.emit("正在处理中...")
		self.signals.progress_changed.emit(0, "准备中...")

		threading.Thread(target=self._do_process, daemon=True).start()

	def _do_process(self):
		try:
			def progress_callback(progress, text):
				self.signals.progress_changed.emit(int(progress), text)

			data_dir = self.data_dir_edit.text().strip()
			time_range = self.time_edit.text().strip()
			quarters = parse_quarters(time_range)

			# 先生成输出目录
			tmp_processor = BatchProcessor(None, progress_callback)
			output_dir = tmp_processor.generate_output_directory(time_range)
			self.signals.log_appended.emit("开始处理数据...")
			self.signals.log_appended.emit(f"时间范围: {time_range}")
			self.signals.log_appended.emit(f"输出目录: {output_dir}")

			if data_dir:
				self.signals.log_appended.emit(f"数据目录: {data_dir}")
				self.signals.log_appended.emit("模式: 从docx文件提取数据")
				excel_path = os.path.join(data_dir, "个人剂量监测各单位编号汇总.xlsx")
				processor = BatchProcessor(excel_path, progress_callback)
				quarters = processor.process_all_quarters(data_dir, time_range)
				result_files = processor.generate_all_summaries(quarters, output_dir, use_historical_data=False)
			else:
				processor = BatchProcessor(None, progress_callback)
				result_files = processor.generate_all_summaries(quarters, output_dir, use_historical_data=True)

			self.signals.result_dir_changed.emit(output_dir)
			self.signals.log_appended.emit("处理完成！")
			self.signals.status_changed.emit("处理完成")

			if 'error' in result_files:
				self.signals.log_appended.emit(f"错误: {result_files['error']}")
			else:
				if 'quarterly' in result_files:
					for quarter in sorted(result_files['quarterly'].keys()):
						self.signals.log_appended.emit(f"季度汇总表: {quarter}季度汇总表.csv")
				if 'annual' in result_files:
					self.signals.log_appended.emit("年度汇总表: 年度汇总表.csv")

		except Exception as e:
			self.signals.log_appended.emit(f"处理过程中出错: {e}")
			self.signals.status_changed.emit("处理失败")
		finally:
			self.signals.enable_controls.emit(True)

	def open_result_directory(self):
		"""在系统文件管理器中打开结果目录"""
		path = self.result_edit.text().strip()
		if not path or not os.path.isdir(path):
			QtWidgets.QMessageBox.warning(self, "提示", "结果目录不存在")
			return
		QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(path))


def main():
	app = QtWidgets.QApplication([])
	win = QtExtractorWindow()
	win.show()
	app.exec()
